package cn.tedu.micro.demo.rabbit.consumer;

import cn.tedu.micro.demo.rabbit.pojo.DelayMessage;
import cn.tedu.micro.demo.rabbit.serializer.MessageSerializer;
import com.rabbitmq.client.Channel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.MessageChannel;
import org.springframework.stereotype.Component;

/**
 * 消费入口类,我希望当前项目进程 有很多消息队列监听,都调用
 * 入口类的方法
 */
@Component
@Slf4j
public class AmqpConsumer {
    @Autowired
    private MessageSerializer<DelayMessage> messageSerializer;
    //消息测试的demo-q
    //1.第一种接参方式 消息体
    /*@RabbitListener(queues = {"demo-q"})
    public void recevie(String msg){
        //每当队列推送给消费者一条消息,这个方法就会调用一次
        log.info("消费开始调用,消息内容:{}",msg);
        //throw new RuntimeException("消费异常");
    }*/
    //2.接收完整消息对象 又有消息体 又有消息属性
    /*@RabbitListener(queues = {"demo-q"})
    public void recevie(Message msg){
        //每当队列推送给消费者一条消息,这个方法就会调用一次
        log.info("消费开始调用,消息内容:{}",msg);
        //throw new RuntimeException("消费异常");
    }*/
    //3. 接收底层连接监听的channel
    /*@RabbitListener(queues = {"demo-q"})
    public void recevie(Channel channel){
        //每当队列推送给消费者一条消息,这个方法就会调用一次
        log.info("消费开始调用,连接对象:{}",channel);
        //throw new RuntimeException("消费异常");
        //手动确认 可以使用这个连接对象
    }*/
    //4.组合入参
    @RabbitListener(queues = {"demo-q"})
    public void recevie(String msg,Message message,Channel channel){
        //每当队列推送给消费者一条消息,这个方法就会调用一次
        log.info("消费开始调用,消息内容:{}",msg);
        log.info("消费开始调用,消息完整对象:{}",message);
        //使用channel+message完整对象中携带的消息tag表示 可以实现确认或者拒绝
        try{
            channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);
        }catch (Exception e){
            log.error("确认失败",e);
        }
    }
    //监听延迟消息的死信队列dlx-queue
    @RabbitListener(queues = {"dlx_q"})
    public void receiveDelay(String json,Message message,Channel channel){
        log.info("消费延迟,消息内容:{}",json);
        DelayMessage delayMsg = messageSerializer.deserialize(json, DelayMessage.class);
        log.info("消费延迟,消息内容反序列化对象:{}",delayMsg);
        try{
            channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);
        }catch (Exception e){
            log.error("消费确认失败",e);
        }
    }
}
